package servlet;

import java.io.IOException;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.annotation.*;

import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.common.util.StringUtils;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage;

public class WxMpServlet extends HttpServlet {

  /**
   * 
   */
  private static final long serialVersionUID = 9136906877347795560L;
  protected WxMpInMemoryConfigStorage config;
  protected WxMpService wxMpService;
  protected WxMpMessageRouter wxMpMessageRouter;

  @Override
  public void init() throws ServletException {
    super.init();

    config = new WxMpInMemoryConfigStorage();
    config.setAppId("wx4f0b28e3435ccdee"); // 设置微信公众号的appid
    config.setSecret("9757e535ee9dc09a6d8f1983a7b0c255"); // 设置微信公众号的app corpSecret
    config.setToken("592704138wxdemo"); // 设置微信公众号的token
    config.setAesKey("AJzv5BumgNNo4yVgSO08SZVsj6i58DXlCPjjRn7C3l0"); // 设置微信公众号的EncodingAESKey

    wxMpService = new WxMpServiceImpl();
    wxMpService.setWxMpConfigStorage(config);

    WxMpMessageHandler handler = new WxMpMessageHandler() {
		@Override
		public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
				Map<String, Object> context, WxMpService wxMpService,
				WxSessionManager sessionManager) throws WxErrorException {
			WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT()
					.content("测试加密消息")
					.fromUser(wxMessage.getToUserName())
					.toUser(wxMessage.getFromUserName()).build();
			return m;
		}
    };

    wxMpMessageRouter = new WxMpMessageRouter(wxMpService);
    wxMpMessageRouter
        .rule()
        .async(false)
        .content("哈哈") // 拦截内容为“哈哈”的消息
        .handler(handler)
        .end();
  }

  @Override protected void service(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {

    response.setContentType("text/html;charset=utf-8");
    response.setStatus(HttpServletResponse.SC_OK);

    String signature = request.getParameter("signature");
    String nonce = request.getParameter("nonce");
    String timestamp = request.getParameter("timestamp");

    System.out.println("signature===" + signature);
    System.out.println("nonce===" + nonce);
    System.out.println("timestamp===" + timestamp);
    
    if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
      // 消息签名不正确，说明不是公众平台发过来的消息
      response.getWriter().println("非法请求");
      return;
    }

    String echostr = request.getParameter("echostr");
    System.out.println("echostr===" + echostr);
    if (StringUtils.isNotBlank(echostr)) {
      // 说明是一个仅仅用来验证的请求，回显echostr
      response.getWriter().println(echostr);
      return;
    }

    String encryptType = StringUtils.isBlank(request.getParameter("encrypt_type")) ?
        "raw" :
        request.getParameter("encrypt_type");

    if ("raw".equals(encryptType)) {
      // 明文传输的消息
      WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(request.getInputStream());
      WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage);
      response.getWriter().write(outMessage.toXml());
      return;
    }

    if ("aes".equals(encryptType)) {
      // 是aes加密的消息
      String msgSignature = request.getParameter("msg_signature");
      WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(request.getInputStream(), config, timestamp, nonce, msgSignature);
      WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage);
      response.getWriter().write(outMessage.toEncryptedXml(config));
      return;
    }

    response.getWriter().println("不可识别的加密类型");
    return;
  }
}